package com.suishoupai.xmb.service;

import com.alibaba.druid.util.StringUtils;
import com.suishoupai.xmb.Security.MyUserDetail;
import com.suishoupai.xmb.dao.CutAuthMapper;
import com.suishoupai.xmb.dao.CutBlacklistMapper;
import com.suishoupai.xmb.dao.CutUserMapper;
import com.suishoupai.xmb.entity.AuthTypeEnum;
import com.suishoupai.xmb.entity.Blacklist;
import com.suishoupai.xmb.entity.RoleEnum;
import com.suishoupai.xmb.entity.User;
import com.suishoupai.xmb.exception.XmbException;
import com.suishoupai.xmb.utils.PasswordUtil;
import com.suishoupai.xmb.utils.SecurityUserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Created by caojian on 2017/4/7.
 */
@Service
public class UserService {
    @Autowired
    private CutUserMapper cutUserMapper;
    @Autowired
    private CutAuthMapper cutAuthMapper;
    @Autowired
    private CutBlacklistMapper cutBlacklistMapper;
    @Autowired
    private SessionRegistry sessionRegistry;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpSession session;
    @Autowired
    private VerificationCodeService verificationCodeService;
    @Value("${user.currentDay.loginFail.max}")
    private int loginFailMaxNum;
    @Value("${auth.verification.code.need.user.loginFail.num}")
    private int needCode8LoginFailNum;//当连续失败登录多少次后需要验证码

    /**
     * 验证密码
     *
     * @param user     用户数据
     * @param password 需要检验的密码
     * @return true 验证通过
     */
    public boolean validatePsd(User user, String password) {
        String email = user.getEmail();
        password = PasswordUtil.encoder(email, password);
        return password.equals(user.getPassword());
    }

    /**
     * 更新密码
     *
     * @param email
     * @param password
     */
    public void updatePsd(String email, String password) {
        password = PasswordUtil.encoder(email, password);

        User updateUser = new User();
        updateUser.setEmail(email);
        updateUser.setPassword(password);

        if (cutUserMapper.updateByPrimaryKeySelective(updateUser) == 0) {
            throw new RuntimeException("更新失败。");
        }
    }

    /**
     * 重置密码
     *
     * @param email
     * @param password
     */
    @Transactional
    public void resetPsd(String email, String password) {
        this.updatePsd(email, password);
        if (cutAuthMapper.deleteByPrimaryKey(email, AuthTypeEnum.RESET_PSD.getValue()) == 0) {
            throw new RuntimeException("删除失败。");
        }
    }

    /**
     * @param userId
     * @return
     */
    public User getUserById(long userId) {
        return cutUserMapper.selectByPrimaryKey(userId);
    }

    /**
     * 登录
     */
    public Long login(String email, String password, String verificationCode) throws XmbException {
        User user = cutUserMapper.loadUserByEmail(email);
        if (user == null) {
            throw XmbException.newError("账号(" + email + ")不存在！");
        }
        Blacklist blacklist = cutBlacklistMapper.selectByPrimaryKey(user.getId());
        if (blacklist != null) {
            throw XmbException.newError("账号(" + email + ")已被系统冻结！(原因：" + blacklist.getDescription() + ")");
        }
        if (user.getLoginFailNum() >= loginFailMaxNum) {
            throw XmbException.newError("当前账号异常！");
        }
        password = PasswordUtil.encoder(email, password);
        //验证码
        if (user.getLoginFailNum() >= needCode8LoginFailNum && StringUtils.isEmpty(verificationCode)) {
            throw XmbException.newVerificationError("需要验证码！");
        }
        if (user.getLoginFailNum() >= needCode8LoginFailNum) {
            verificationCodeService.validateImageCode(verificationCode, session);
        }
        //验证密码
        if (!user.getPassword().equals(password)) {
            cutUserMapper.loginFailByPrimaryKey(user.getId());
            if (user.getLoginFailNum() >= needCode8LoginFailNum - 1) {//下次登录需要验证码
                throw XmbException.newVerificationError("密码错误！");
            }
            throw XmbException.newError("账号与密码不匹配！");
        }
        //重置登录失败次数（置为0）
        if (cutUserMapper.resetLoginFailByPrimaryKeyWhenLoginFailNum(user.getId(), user.getLoginFailNum()) != 1) {
            throw new RuntimeException("登录成功后，重置登录失败次数失败。可能是并发导致（LoginFailNum!=获取到的LoginFailNum）！userId:" + user.getId());
        }
        //处理Security
        SecurityUserUtil.setAuth(user);
        sessionRegistry.registerNewSession(request.getSession().getId(), new MyUserDetail(user));
        return SecurityUserUtil.hasRole(RoleEnum.ADMIN) ? null : user.getId();//管理员不返回ID
    }
}
